#include "AsteriskSearchEngine.h"
#include "CommutativityGenerator.h"

AsteriskSearchEngine::AsteriskSearchEngine(Query *query)
	: SearchEngine("AsteriskSearchEngine", query)
{
}

AsteriskSearchEngine::~AsteriskSearchEngine()
{	
}

void AsteriskSearchEngine::search()
{
	QueryStorage *qs = new QueryStorage();
	int startpos = 0;

	generator = generators.front();

	qs->addQuery(new QueryInfo(query, queryNumber));
	generator->generate(query, qs, startpos, &queryNumber);

	findCosts(qs);

	if (qs->queries.begin() != qs->queries.end())
	{
		std::sort(qs->queries.begin() + 1, qs->queries.end(), sort_by_cost);
	}

	search(qs, startpos + 1);

	qOut->printOptimizationResults(getName(), min_query, min_cost, (*qs->queries.begin())->cost, timer->getMilliseconds());

	qs->queries.erase(qs->queries.begin());

	delete qs;
}

void AsteriskSearchEngine::search(QueryStorage *qs, int startpos)
{
	if (qs->empty())
	{
		return;
	}

	qOut->printQueries(qs, "output/", getName());

	for (std::vector <QueryInfo *> :: iterator i = qs->queries.begin(); i != qs->queries.end(); i++)
	{
		qOut->printQuery(*i, current);
			
		if (i - qs->queries.begin() > 1)
		{
			continue;
		}

		if (qs->queries.size() > 1)
		{
			if ((*qs->queries.begin())->cost <= (*(qs->queries.begin() + 1))->cost)
			{
				if (i != qs->queries.begin())
				{
					continue;
				}
			}
			else
			{
				if (i != qs->queries.begin() + 1)
				{
					continue;
				}
			}
		}

		QueryStorage *qst = new QueryStorage();

		qst->addQuery(*i);

		bool result = generator->generate((*i)->query, qst, startpos, &queryNumber);
		
		int t = current;
		current = (*i)->number;
		
		if (result)
		{
			findCosts(qst);

			if (qst->queries.begin() != qst->queries.end())
			{
				std::sort(qst->queries.begin() + 1, qst->queries.end(), sort_by_cost);
			}

			search(qst, startpos + 1);
		}
		else
		{
			if (++currGenerator >= generators.size())
			{
				--currGenerator;
			}
			else
			{
				generator = generators[currGenerator];
				search(qst, 0);
				generator = generators[--currGenerator];
			}
		}

		qst->queries.erase(qst->queries.begin());

		current = t;

		delete qst;
	}
}